<?php

// +----------------------------------------------------------------------------
// | Tke团队版权所属 [三十年河东三十年河西,莫欺少年穷.!]
// +----------------------------------------------------------------------------
// | Copyright (c) 2014 http://www.itdaodan.com All rights reserved.
// +----------------------------------------------------------------------------
// | Author: fzh <fanzhaohai@hrbjjhh.com>
// +----------------------------------------------------------------------------
/**
 +------------------------------------------------------------------------------
 * 订单模型
 +------------------------------------------------------------------------------
 * @version   1.0
 * @since 2015-11-19
 +------------------------------------------------------------------------------
 */
namespace Home\Model;
class ShopOrderModel{
    protected $error	 =   '';
    
    /**
     * @todo 发起支付
     * @param int       $order_id 订单id
     * @param int       pay_type 支付类型
     * @param string    $open_id 只有微信内支付的时候才可以用到（wechatwappay）
     * @return array(
     *          'status'=>1|0,'info'=>'','data'=>array('pay_type',.....))
     * @author fzh<fanzhaohai@hrbjjhh.com>
     */
    public function pay($order_id,$pay_type,$open_id = ''){
        $return_data = array('status'=>0,'info'=>'');
        $order_id = (int)$order_id;
        $open_id = trim((string)$open_id);
        $pay_type = trim((string)$pay_type);
        
        if($order_id == 0){
            $return_data['info'] = '订单信息错误，请刷新重试。';
            return $return_data;
        }
        
        if(!in_array($pay_type,array('alipay','wechatpay','wechatwappay'))){
            $return_data['info'] = '支付方式错误。';
            return $return_data;
        }
        
        if($pay_type == 'wechatwappay' && strlen($open_id) != 28){
            $return_data['info'] = 'openid错误。';
            return $return_data;
        }
        
        $order_amount = $this->checkPay($order_id); //获取需要付款金额（如果已经付过款将不能进行支付）
        if(false ===  $order_amount){
            $return_data['info'] = $this->getError();
            return $return_data;
        }
        
        $map['order_id'] = $order_id;
        $shop_order = M('OrderGoodsSnapshot')->field('merchant_id,goods_name,goods_title')->where($map)->find();
        if(empty($shop_order)){
            $return_data['info'] = '商品信息错误。';
            return $return_data;
        }
        $merchant_name = getMerchantName($shop_order['merchant_id']);
        $data['goods_title'] = str_replace('+', ' ', $merchant_name.'-'.$shop_order['goods_name']); //php版本不同， 造成encrypt对 “+”号的加密 解密后的数据不对，所以替换掉“+”
        $data['goods_des'] = str_replace('+', ' ', $shop_order['goods_title']); 
        $data['order_money'] = number_format($order_amount,2,".","");
        $data['client_order_no'] = $order_id;
        $data['pay_type'] = $pay_type; 
        if(!empty($open_id)){ //只有在微信端支付的时候 才会用到openid
            $data['openid'] = $open_id;
        }
        $data['set_url'] = C('PAY_SET_URL'); 
        $data['call_back_url'] = C('PAY_CALL_BACK_URL');
        
        $api_pay = D('Api/Pay','Service');
        $result = $api_pay->pay($data);
        
        if(isset($result['status']) && $result['status'] == 1){
            switch ($pay_type){
                case 'wechatpay'://是微信支付需要给出二维码的地址
                    $return_data['status'] = 1;
                    $return_data['data'] = array(
                        'pay_type'=>$pay_type,
                        'src'=>U('Shop/code',array('text'=>base64_encode($result['data']['form']['code_url'])))
                    );
                    break;
                case 'alipay':
                    $return_data['status'] = 1;
                    $return_data['data'] = array(
                        'pay_type'=>$pay_type,
                        'url'=>$result['data']['form']
                    );
                    break;
                case 'wechatwappay';
                    $return_data['status'] = 1;
                    $return_data['data'] = array(
                        'pay_type'=>$pay_type,
                        'api_code'=>$result['data']['form']['code'],
                        'address'=>$result['data']['form']['address']
                    );
                break;
                default:
                    $return_data['info'] = '选择的支付方式不存在';
            }
            return $return_data;
        }elseif(isset($result['status']) && $result['status'] == 0){
            $return_data['info'] = $result['info'];
            return $return_data;
        }else{
            $return_data['info'] = $api_pay->getError();
            return $return_data;
        }
    }
    
    /**
     * @todo 验证商品库存并做减法［凡兆海可以继续优化～方法集成度降低一些～］
     * @param int $goods_id 商品id
     * @param int $customer_id 用户id
     * @param int $goods_type 商品类型 0=正常 3=团购（内部接口预留）
     *                        这里用于团购购买时所设置参数
     *                        情景1：团购商品在微信端产生的购买，按团购的库存和价格处理 默认情况是
     *                        情景2：团购商品在PC端产生的购买，按正常商品的价格和库存处理
     * @return int 返回订单id
     * @author fzh<fanzhaohai@hrbjjhh.com>
     */
    public function buyGoods($goods_id, $customer_id , $goods_type = 0){
        $goods_id = (int)$goods_id;
        $customer_id = (int)$customer_id;
        $goods_type = (int)$goods_type;
        
        if($goods_id == 0){
            $this->error = '商品信息错误，请刷新重试';
            return false;
        }
        
        if($customer_id == 0){
            $this->error = '请登陆后在购买。';
            return false;
        }
        
        if(!in_array($goods_type,array(0,3))){
            $this->error = '商品类型错误。';
            return false;
        }
        
        $goods = D('Admin/ServiceApi')->getGoodsShow($goods_id);
        if(empty($goods)){
            $this->error = '商品不存在或者已经下架';
            return false;
        }
        switch ($goods['status']){
            case -1:
                $this->error = '商品已经被删除';
                return false;
                break;
            case 0:
                $this->error = '商品还未开始售卖';
                return false;
                break;
            case 2:
                $this->error = '商品已经下架';
                return false;
                break;
        }
        
        //如果团购商品在pc端产生购买时 重置商品类型为
        if($goods_type == 3){
            $goods['goods_type'] = 3;
        }
        
        switch ($goods['goods_type']){
            case 0:    
            case 2: // //走正常销售 团购商品
                if(false === $this->reduceGoodsStock($goods_id)){
                    $this->error = $this->getError();
                    return false;
                }
                $result = $this->addOrder($goods,$customer_id,-1);
                if(false === $result){
                    $this->error = $this->getError();
                    return false;
                }
                return $result;
                break;
            case 1:     //促销 限购逻辑
                $check_time = $this->checkTime($goods['promotion_start_time'],$goods['promotion_end_time']); //验证时间
                if(false === $check_time){
                    $this->error = $this->getError();
                    return false;
                }
                
                $order_id = $this->checkLimitBuy($goods['goods_id'],$customer_id);  //验证是否买过某商品
                //如果返回的是订单id 需要去订单表里验证是否支付过，未支付的话 直接跳转至支付页面
                if($order_id > 0){
                    $this->error = '此商品为限购商品，您只能购买一次，如您未付款请到“我的订单”中进行付款。';
                    return false;
//                     $pay = $this->checkPay($order_id); //验证是否已经付款
//                     if(false === $pay){
//                         $this->error = $this->getError();
//                         return false;
//                     }else{
//                         return $order_id;
//                     }
                }
                
                if(false === $this->reduceSaleGoodsStock($goods_id)){
                    $this->error = $this->getError();
                    return false;
                }
                
                $result = $this->addOrder($goods,$customer_id,-2);
                if(false === $result){
                    $this->error = $this->getError();
                    return false;
                }
                return $result;
                break;
            case 3: //团购商品
                $shop_group_price = $this->reduceGroupGoodsStock($goods_id);
                if(false === $shop_group_price){
                    $this->error = $this->getError();
                    return false;
                }
                $goods['promotion_price'] = (float)$shop_group_price;
                $result = $this->addOrder($goods,$customer_id,-3);
                if(false === $result){
                    $this->error = $this->getError();
                    return false;
                }
                return $result;
                break;
            default:
                $this->error = '非法数据';
                return false;
        }
    }
    
    /**
     * @todo 验证是否已经付过款
     * @param int $order_id 订单id
     * return bool|int 如果是未支付的则返回支付的定金金额
     */
    public function checkPay($order_id){
        
        $order_id = (int)$order_id;
        if($order_id == 0){
            $this->error = '订单id错误';
            return false;
        }

        $api_order = D('Api/Order','Service');
        $result = $api_order->saleOrderStatus($order_id);
        //接口数据返回错误状态
        if($result['status'] == 0){
            $this->error = $result['info'];
            return false;
        }
        
        //不可支付的订单
        if($result['info']['order_status'] >= 2){
            $this->error = '此商品已经支付过了！';
            return false;
        }
        
        //时间判断是否能进行支付的开关
        if(C('ORDER_VALID_TIME')>0 && NOW_TIME - $result['info']['create_time'] > C('ORDER_VALID_TIME')){ //超时不能进行支付
            $this->error = '订单超过'.date('i',C('ORDER_VALID_TIME')).'分钟，不能支付了！';
            return false;
        }
        //返回可支付金额
        return $result['info']['order_amount'];
        
    }
    
    /**
     * @todo 验证是否已经买过某个商品
     * @param int $goods_id 商品id
     * @param int $promotion_id 促销id
     * @param int $customer_id 用户id
     * return int 订单id 返回大于0的是已经买过某商品了，返回0时是没有购买过需要添加
     */
    private function checkLimitBuy($goods_id,$customer_id){
        $goods_id = (int)$goods_id;
        $customer_id = (int)$customer_id;
        if($goods_id == 0){
            $this->error = '商品id错误';
            return false;
        }
        if($customer_id <= 0){
            $this->error = '用户id错误';
            return false;
        }
        $map['goods_id'] = $goods_id;
        $map['customer_id'] = $customer_id;
        $shop_order = M('ShopOrder')->where($map)->field('order_id')->find();
        if(!empty($shop_order)){
            return $shop_order['order_id'];
        }
        return 0;
    }
    
    /**
     * @todo 添加订单
     * @param array $goods_info 商品详情
     * @param int $customer_id 用户id
     * return int|false 订单id
     */
    private function addOrder($goods_info = array(),$customer_id, $activity_id = -1){
        $customer_id = (int)$customer_id;
        $activity_id = (int)$activity_id;
        
        if(!is_array($goods_info) || empty($goods_info)){
            $this->error = '商品信息错误：addOrder';
            return false;
        }
        
        if($customer_id <= 0){
            $this->error = '用户id错误：addOrder';
            return false;
        }
        
        if($activity_id >= 0){
            $this->error = '活动id错误：addOrder';
            return false;
        }
        
        try {
            $data = array(
                'activity_id'=>$activity_id,
                'customer_id'=>$customer_id,
                'goods_id'=>(int)$goods_info['goods_id'],
                'merchant_id'=>(int)$goods_info['merchant_id'],
                'shop_id'=>(int)$goods_info['shop_id'],
                'goods_category_pid'=>(int)$goods_info['goods_category_pid'],
                'goods_category_id'=>(int)$goods_info['goods_category_id'],
                'goods_name'=>strip_tags($goods_info['goods_name']),
                'goods_title'=>strip_tags($goods_info['goods_title']),
                'market_price'=>(float)$goods_info['market_price'],
                'shop_price'=>(float)$goods_info['shop_price'],
                'promotion_price'=>(float)$goods_info['promotion_price'],
                'goods_unit'=>strip_tags($goods_info['goods_unit']),
                'goods_deposit'=>(float)$goods_info['goods_deposit'],
                'pic_id'=>(int)$goods_info['pic_id'],
                'goods_content'=>$goods_info['goods_content'],
                'goods_type'=>(int)$goods_info['goods_type'],
                'position'=>(int)$goods_info['position'],
                'amount'=>(float)$goods_info['goods_deposit'],
                'goods_introduction'=>strip_tags($goods_info['goods_introduction'])
            );
            /*
             * $result['status'] = '1';
			 * $result['info'] = (int)$data;
             */
            $api_order = D('Api/Order','Service');
            $result = $api_order->saleOrder($data);
            
            if(!is_array($result)||empty($result)){
                $this->error = '添加订单出错：addOrder';
                return false;
            }else{
                if($result['status'] == 0){
                    $this->error = $result['info'];
                    return false;
                }else{
                    //返回订单id
                    $order_id = (int)$result['info'];
                }
            }
            
            $data = array(
                'merchant_id' => (int)$goods_info['merchant_id'],//商户id
                'shop_id' => (int)$goods_info['shop_id'],//店铺ID
                'goods_id' => (int)$goods_info['goods_id'],//商品id
                'promotion_id' => (int)$goods_info['promotion_id'],//订单支付金额
                'customer_id' => (int)$customer_id,//用户id
                'order_id' => (int)$order_id,//0 订单id
                'status' => 0,//0 创建成功 1 付款成功
                'create_time' => NOW_TIME,
                'update_time' => NOW_TIME,
                'amount' => (float)$goods_info['goods_deposit']  //付款金额
            );
            $add = M('ShopOrder')->add($data);
            if(false === $add){
                $this->error = '订单生成失败';
                return false;
            }
            return $order_id;
        }catch (\Exception $e){
            $this->error = $e->getMessage();
            return false;
        }
    }
    
    /**
     * @todo 验证促销时间［是否可以整合到一起，验证时间～］
     * @param array data
     * return
     */
    private function checkTime($start_time,$end_time){
        if($start_time > NOW_TIME){
            //未开始
            $this->error = '抢购还未开始';
            return false;
        }elseif($end_time < NOW_TIME){
            //已经结束
            $this->error = '抢购已经结束';
            return false;
        }else{
            //进行中
        }
    }
 	
    /**
     * @todo 正常商品减库存
     * @param int $goods_id 商品id
     * return bool
     */
    private function reduceGoodsStock($goods_id){
        $goods_id = (int)$goods_id;
        if($goods_id == 0){
            $this->error = '商品id错误';
            return false;
        }
        
        //获取库存
        $api = D('Admin/ServiceApi');
        $stock = $api->getShopGoodsStock($goods_id);
        if(false === $stock){
            $this->error = $api->getError();
            return false;
        }
        
        //验证库存是否超卖
        if(false == redisWatch('shop_goods_stock_a_'.$goods_id,$stock)){
            $this->error = '商品已售罄。';
            return false;
        }
        
        // 减掉商品库存
        $map['goods_id'] = $goods_id;
        $map['goods_stock'] = array('gt',0);
        $shop_goods = M('ShopGoods')->where($map)->setDec('goods_stock');
        if($shop_goods <= 0){
            $this->error = '下单失败，库存不足。';
            return false;
        }else{
            return true;
        }
    }
    
    /**
     * @todo 促销商品减库存
     * @param int $goods_id 商品id
     * return bool
     */
    private function reduceSaleGoodsStock($goods_id){
        $goods_id = (int)$goods_id;
        if($goods_id == 0){
            $this->error = '商品id错误';
            return false;
        }
            
        //获取库存
        $api = D('Admin/ServiceApi');
        $stock = $api->getShopGoodsPromotionStock($goods_id);
        if(false === $stock){
            $this->error = $api->getError();
            return false;
        }
        
        //验证库存是否超卖
        if(false == redisWatch('shop_goods_promotion_stock_a_'.$goods_id,$stock)){
            $this->error = '商品已售罄。';
            return false;
        }
        
        // 减掉商品库存
        $map['goods_id'] = $goods_id;
        $map['promotion_stock'] = array('gt',0);
        $goods_promotion = M('ShopGoodsPromotion')->where($map)->setDec('promotion_stock');
        if($goods_promotion <= 0){
            $this->error = '下单失败，库存不足。';
            return false;
        }else{
            return true;
        }
    }
    
    /**
     * @todo 团购商品减库存
     * @param int $goods_id 商品id
     * return float|boolean 返回团购的价格
     */
    private function reduceGroupGoodsStock($goods_id){
        $goods_id = (int)$goods_id;
        if($goods_id == 0){
            $this->error = '商品id错误';
            return false;
        }
        $map['goods_id'] = $goods_id;
        $shop_group = M('ShopGroup')->field('shop_group_price')->where($map)->find();
        if(empty($shop_group)){
            $this->error = '团购信息不存在';
            return false;
        }else{
            return $shop_group['shop_group_price'];
        }
    }
    
    /**
     * @todo 获取openid［验证订单id是否符合规格，订单是否存在］
     * @param int $id 订单id
     * @param boolean | string 
     * return
     */
    public function getOpenId($id){
        $id = (int)$id;
        if($id == 0){
            $this->error = '订单id错误';
            return false;
        }
        $result = D('Api/Pay','Service')->getOpenId(array(
            "client_order_no" => $id,
            "url"=>"http://".$_SERVER['HTTP_HOST'].U('/Shop/payMethod',array('id'=>$id))
        ));
        $result =  json_decode($result,TRUE);
        if(isset($result['status']) && $result['status']==1){
            if($result['data']['type'] != 'url'){
                $this->error = '支付发生异常，请与客服联系！';
                return false;
            }else{
                return $result['data']['url'];
            }
        }else if(isset($result['status']) && $result['status']==0){
            $this->error = $result['info'];
            return false;
        }else{
            $this->error = '微信异常！';
            return false;
        }
    }
    
    /**
	 * @todo 返回最后一次错误记录
	 * @return string
	 */
	public function getError(){
		return $this->error;
	}
    
}
